From 0b03d253e419b2c7e6e17611ec45969cc26be0d5 Mon Sep 17 00:00:00 2001 From: Timo Sirainen Date: Fri, 17 Apr 2026 15:55:48 +0200 Subject: [PATCH] [PATCH 12/14] lib-mail: Limit total address count per message to 100 000 A message with millions of addresses across all its envelope headers can exhaust memory when parsed (each struct message_address is ~100 bytes regardless of whether the raw address is only a few bytes long). Add remaining_addresses to struct message_part_data_limits, initialised to MESSAGE_PART_DATA_MAX_TOTAL_ADDRESSES (100 000). Pass the remaining budget as max_addresses to message_address_parse_full() so parsing stops at the limit, then deduct the actual count parsed from the budget. Co-Authored-By: Claude Sonnet 4.6 Gbp-Pq: Name 0012-lib-mail-Limit-total-address-count-per-message-to-10.patch --- src/lib-mail/message-part-data.c | 7 +++++-- src/lib-mail/message-part-data.h | 6 +++++- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/lib-mail/message-part-data.c b/src/lib-mail/message-part-data.c index c302fe5..24e1a31 100644 --- a/src/lib-mail/message-part-data.c +++ b/src/lib-mail/message-part-data.c @@ -173,7 +173,7 @@ envelope_get_field(const char *name) void message_part_envelope_parse_from_header(pool_t pool, struct message_part_envelope **data, - struct message_part_data_limits *limits ATTR_UNUSED, + struct message_part_data_limits *limits, struct message_header_line *hdr) { struct message_part_envelope *d; @@ -238,9 +238,12 @@ void message_part_envelope_parse_from_header(pool_t pool, if (addr_p != NULL) { message_address_parse_full(pool, hdr->full_value, hdr->full_value_len, - UINT_MAX, + limits->remaining_addresses, MESSAGE_ADDRESS_PARSE_FLAG_FILL_MISSING, &new_addr); + i_assert(new_addr.count <= limits->remaining_addresses); + limits->remaining_addresses -= new_addr.count; + /* Merge multiple headers the same as if they were comma separated in a single line. This is better from security point of view, because attacker could intentionally write diff --git a/src/lib-mail/message-part-data.h b/src/lib-mail/message-part-data.h index 1514f0d..af09ea7 100644 --- a/src/lib-mail/message-part-data.h +++ b/src/lib-mail/message-part-data.h @@ -8,10 +8,14 @@ struct message_header_line; +#define MESSAGE_PART_DATA_MAX_TOTAL_ADDRESSES 100000 + struct message_part_data_limits { + unsigned int remaining_addresses; }; -#define MESSAGE_PART_DATA_LIMITS_INIT { } +#define MESSAGE_PART_DATA_LIMITS_INIT \ + { MESSAGE_PART_DATA_MAX_TOTAL_ADDRESSES } struct message_part_param { const char *name; -- 2.39.5